package com.example.seleniumautotest.controller;

import com.example.seleniumautotest.emun.TestCase;
import com.example.seleniumautotest.utils.DelayUtils;
import com.example.seleniumautotest.utils.DriverService;
import com.example.seleniumautotest.utils.POIHandle;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.logging.LogEntries;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.util.Iterator;
import java.util.Objects;

@Slf4j
@Component
public class StartMain {

    @Autowired
    private DriverService driverService;
    @Autowired
    private Environment environment;
    @Autowired
    private POIHandle poiHandle;
    @Autowired
    private OverallConfigInit overallConfigInit;
    @Autowired
    private DelayUtils delayUtils;
    @Autowired
    private CustomMethod customMethod;

    private ChromeDriver chromeDriver;
    private XSSFSheet initSheet;
    private WebElement CurrentElement;

    // 入口
    public void start() {

        // 加载驱动
        chromeDriver = driverService.initDriver();

        // 打开首页
        String homePath = environment.getProperty("customConfig.homePath");
        overallConfigInit.overallLoad(chromeDriver,homePath);

        // 初始化testCase文件 [配置执行第几个表sheet的测试用例]
        Integer sheetIndex = Integer.valueOf(Objects.requireNonNull(environment.getProperty("customConfig.sheetIndex")));
        initSheet = poiHandle.init(environment.getProperty("customConfig.filePath"), sheetIndex);

        // 执行测试用例
        int rowCount = poiHandle.getRowCount(initSheet);
        if (rowCount <= 0){return;}
        for (int i = 1; i < rowCount; i++) {
            // 输出执行日志
            printLog(i,initSheet);
            // process
            runProcess(i);
        }
        log.info("程序执行完毕，共执行{}条用例!",rowCount-1);

        // 关闭driver
        customMethod.closeDriver(chromeDriver);
    }

    // 输出执行日志
    private void printLog(int index, XSSFSheet initSheet) {
        String logString = "";
        Iterator<Cell> iterator = poiHandle.getRow(initSheet, index).iterator();
        for (Iterator<Cell> it = iterator; it.hasNext(); ) {
            Object tmp = it.next();
            logString = logString + "  " + tmp.toString();
        }
        log.info("当前执行的事件： ID {}", logString);
    }

    // 事件具体执行
    private void runFunction(String type, WebElement webElement, String contentText){
        Actions actions = new Actions(chromeDriver);
        switch (type){
            case "单击":
                webElement.click();
                break;
            case "双击":
                actions.doubleClick(webElement).perform();
                break;
            case "输入":
                webElement.clear();
                webElement.sendKeys(contentText);
                break;
            case "拖动":
                String[] split = contentText.split(",");
                int split_x = Integer.valueOf(split[0]);
                int split_y = Integer.valueOf(split[1]);
                log.info("x偏移量：{}   y偏移量：{}",split_x,split_y);
                // actions.dragAndDropBy(webElement,split_x,split_y).perform();
                actions.clickAndHold(webElement).moveByOffset(split_x,split_y).release().perform();
                delayUtils.delay(2);
                break;
            case "长按":
                actions.clickAndHold(webElement).perform();
                break;
            case "抬起":
                actions.release(webElement).perform();
                break;
            case "刷新":
                chromeDriver.navigate().refresh();
                break;
            default:
                break;
        }
    }

    // 根据类型查找控件
    private WebElement searchElement(String type, String elementID){

        WebElement element = null;
        int sum = 0;
        int retry = Integer.valueOf(environment.getProperty("retryCount"));

        if (type.equals("CLASS_NAME")){

            // retry查找ByClassName
            findElementByClassName(sum, retry, elementID);
            if (Objects.isNull(CurrentElement)){
                throw new NoSuchElementException("未找到元素: " + elementID);
            }
            return CurrentElement;

        }else if (type.equals("CSS_SELECTOR")){

            // retry查找ByCssSelector
            findElementByCssSelector(sum, retry, elementID);
            if (Objects.isNull(CurrentElement)){
                throw new NoSuchElementException("未找到元素: " + elementID);
            }
            return CurrentElement;

        }else if (type.equals("-")){

            // 不需要查找直接返回
            return null;

        }else {
            throw new RuntimeException("控件类型不支持-或者找不到: " + type);
        }
    }

    // findElement by classname
    private void findElementByClassName(int sum, int retry, String elementID){

        CurrentElement = null;

        WebElement element =null;
        try {
            element = chromeDriver.findElement(By.className(elementID));
            CurrentElement = element;
        }catch (NoSuchElementException exception){
            if(++sum <= retry){
                // 失败重试
                log.info("查找失败，正在进行重试第 {} 次……",sum);
                delayUtils.delay(3);
                findElementByClassName(sum,retry,elementID);
            }
        }catch (Exception e){
            log.info("未知查找异常");
            e.printStackTrace();
        }
    }

    // findElement by cssSelector
    private void findElementByCssSelector(int sum, int retry, String elementID){

        CurrentElement = null;

        WebElement element = null;
        try {
            element = chromeDriver.findElement(By.cssSelector(elementID));
            CurrentElement = element;
        }catch (NoSuchElementException exception){
            if(++sum <= retry){
                // 失败重试
                log.info("查找失败，正在进行重试第 {} 次……",sum);
                delayUtils.delay(3);
                findElementByCssSelector(sum,retry,elementID);
            }
        }catch (Exception e){
            log.info("未知查找异常");
            e.printStackTrace();
        }
    }


    // 控制执行流程
    private void runProcess(int i){

        String searchType = poiHandle.getCell(initSheet, i, TestCase.SEARCH_TYPE.getType()).getStringCellValue();
        String elementID = poiHandle.getCell(initSheet, i, TestCase.ELEMENT_ID.getType()).getStringCellValue();
        String methodType = poiHandle.getCell(initSheet, i, TestCase.METHODTYPE.getType()).getStringCellValue();
        int delayTime = (int) poiHandle.getCell(initSheet, i, TestCase.DELAY_TIME.getType()).getNumericCellValue();
        int eachCount = (int) poiHandle.getCell(initSheet, i, TestCase.EACH_COUNT.getType()).getNumericCellValue();
        String contentText = poiHandle.getCell(initSheet, i, TestCase.INPUT_STRING.getType()).getStringCellValue();

        // 根据次数循环执行
        for (int j = 0; j < eachCount; j++) {
            // 获取控件
            WebElement webElement = searchElement(searchType, elementID);
            // 执行
            runFunction(methodType, webElement, contentText);
            // 延迟
            delayUtils.delay(delayTime);
        }
    }
}
